package com.thermofisher.dsc.amanda.auth.service.impl;

import com.thermofisher.dsc.amanda.auth.mapper.UserMapper;
import com.thermofisher.dsc.amanda.auth.service.UserService;
import com.thermofisher.dsc.amanda.common.exception.BaseException;
import com.thermofisher.dsc.amanda.common.exception.ExceptionCode;
import com.thermofisher.dsc.amanda.common.util.JwtUtil;
import com.thermofisher.dsc.amanda.model.dto.auth.JwtLoginRequest;
import com.thermofisher.dsc.amanda.model.po.auth.User;
import com.thermofisher.dsc.amanda.security.jwt.JWTInfo;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

/**
 * Created by wenjie.yang on 1/3/2019.
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

  @Autowired
  private UserMapper userMapper;

  @Autowired
  private PasswordEncoder passwordEncoder;

  @Autowired
  private JwtUtil jwtUtil;

  @Value("${bio.auth.time:120000}")
  private Long timeOut;

  @Value("${email.server.host}")
  private String serverHost;

  @Value("${email.server.port}")
  private String serverPort;

  @Value("${email.server.account}")
  private String account;
  @Value("${email.server.password}")
  private String password;

  @Override
  public String login(JwtLoginRequest loginUser) throws Exception {
    String password = loginUser.getPassword();
    String userName = loginUser.getUsername();
    User record = new User();
    record.setUserName(userName);
    User user = userMapper.selectOne(record);
    if (user != null && passwordEncoder.matches(password, user.getPassword())) {
      return jwtUtil.generateToken(
          new JWTInfo(user.getUserName(), user.getId() + "", new ArrayList<>()));
    } else {
      throw new BaseException(ExceptionCode.USER_OR_PASSWORD_WRONG, "user or password wrong");
    }
  }


  @Override
  public User getUser() {
    List<User> users = userMapper.selectAll();
    return users.get(0);
  }


  @Override
  public List<Long> getCurrentHierarchyUserIds(Long currentId, List<Long> ids) {
    List<User> userList = userMapper.getChildIds(currentId);
    List<Long> userIds = userList.stream().map(User::getId).collect(Collectors.toList());
    ids.addAll(userIds);
    userList.forEach(user -> {
      if (user.getLeaderId() != null) {
        getCurrentHierarchyUserIds(user.getId(), ids);
      }
    });
    ids.add(currentId);
    return ids;
  }

  @Override
  public String authLogin(String username, Long createLong) throws Exception {
    log.info(username);
    if (System.currentTimeMillis() - createLong > timeOut) {
      throw new BaseException(ExceptionCode.USER_TOKEN_FORBIDDEN_OR_EXPIRED, "token timeout");
    }
    if (!username.isEmpty()) {
      User user = new User();
      user.setUserName(username);
      User userDetails = userMapper.selectOne(user);
      if (userDetails == null) {
        log.info("email {} is not in database", username);
        throw new BaseException(ExceptionCode.USER_TOKEN_FORBIDDEN_OR_EXPIRED, "user is null");
      }
      return jwtUtil.generateToken(
          new JWTInfo(userDetails.getUserName(), userDetails.getId() + "", new ArrayList<>()));
    } else {
      log.info("email is null");
      throw new BaseException(ExceptionCode.USER_TOKEN_FORBIDDEN_OR_EXPIRED, "username is null");
    }
  }

  @Override
  public boolean isValidFromThridParty(String message, String signature) {
    return jwtUtil.isValidFromThirdParty(message, signature);
  }
}
